package main;


import java.io.IOException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.log4j.Logger;
import org.apache.poi.POIXMLDocument;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;
import org.dom4j.DocumentException;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr;

import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Record;

import wordUtil.docExport.CustomXWPFDocument;

/**
 * 解析word表格
 */
public class MainAnalysDocx {

	public static Logger logger = Logger.getLogger(MainAnalysDocx.class);

	public static void main(String[] args) throws DocumentException, IOException {
		// 解析docx
		analysDocx();
	}

	/**
	 * 解析DOCX模板
	 * 
	 * @throws IOException
	 */
	public static void analysDocx() throws IOException {

		Class<MainAnalysDocx> clazz = MainAnalysDocx.class;
		URL resource = clazz.getResource("/国家电网公司变电检测通用管理规定 第1分册 红外热像检测细则—试用版.docx");

		String path = URLDecoder.decode(resource.getPath(), "UTF-8");

		Map<String, List<Record>> results = analyseDocxFile(path); // 解析doc文件

		logger.info("******************docx解析后的对象");

		for (Entry<String, List<Record>> tableData : results.entrySet()) {

			String key = tableData.getKey();
			logger.info(key);

			List<Record> groupOrFieldList = tableData.getValue();
			for (Record groupOrField : groupOrFieldList) {
				String category = groupOrField.getStr("field_type"); // 字段归类：一、基本信息
				category = category.replaceAll(".+(?<=、)", ""); // 取、后的文本：将一、替换为空
				boolean isgroup = groupOrField.getBoolean("isgroup");

				// logger.info(String.format("%s %s %s %s %s", key, fieldName, category, groupOrField.getStr("group_name"), groupOrField.get("sort")));

				if (isgroup) { // 组
					System.out.println(groupOrField);
					List<Record> childList = groupOrField.get("data");

					for (Record child : childList) { // 组的子数据
						System.out.println(child);
					}
				} else { // 非组数据
					System.out.println(groupOrField);
				}
			}
		}
		System.out.println("ok!");
	}

	/**
	 * <pre>
	 * 表
	 * 		组
	 * 			字段、字段归类
	 * 		字段、字段归类
	 * 
	 * Map<List<Record>>
	 * </pre>
	 * 
	 * @param template
	 * @return
	 * @throws IOException
	 */
	public static Map<String, List<Record>> analyseDocxFile(String template) throws IOException {

		Map<String, List<Record>> tableDatas = new HashMap<>();

		OPCPackage pack = POIXMLDocument.openPackage(template);
		CustomXWPFDocument doc = new CustomXWPFDocument(pack);

		// 处理表格
		Iterator<XWPFTable> it = doc.getTablesIterator();
		int tableCount = 1;
		while (it.hasNext()) {

			XWPFTable table = it.next(); // 表
			logger.info("*");
			logger.info("*");
			logger.info("******************************表 " + tableCount + "******************************");
			logger.info("*");
			logger.info("*");

			List<Record> table1Data = new ArrayList<>(); // 一张表的数：字段名、字段类型、组名、排序

			List<XWPFTableRow> rows = table.getRows(); // 行
			String fieldType = "";
			for (int i = 0; i < rows.size(); i++) {
				XWPFTableRow row = rows.get(i);

				Map<Integer, String> map = getRowData(row);
				boolean rowisNull = rowIsNull(row, (i + 1));
				if (map.size() == 1) {
					fieldType = map.get(0);
				} else {

					Set<Entry<Integer, String>> entrySet = map.entrySet();

					if (!rowisNull) { // 这一行全不为空，则是组
						String groupName = "组" + i;

						Record group = new Record();
						group.set("sort", i + 1);
						group.set("name", groupName + (i + 1));
						group.set("field_type", fieldType);
						group.set("isgroup", true);

						List<Record> data = new ArrayList<>();
						for (Entry<Integer, String> temp : entrySet) {
							Record r = new Record();
							String value = temp.getValue();
							// logger.info("第 " + (i + 1) + "行 " + temp.getKey() + "列 " + value);
							if (StrKit.notBlank(value)) {
								r.set("sort", temp.getKey());
								r.set("name", value);
								r.set("group_name", groupName);
								r.set("field_type", fieldType);
								r.set("isgroup", false);
								data.add(r);
							}
						}
						group.set("data", data);
						table1Data.add(group);
					} else {

						for (Entry<Integer, String> temp : entrySet) {
							Record r = new Record();
							String value = temp.getValue();
							if (StrKit.notBlank(value)) {
								r.set("sort", temp.getKey());
								r.set("name", value);
								r.set("field_type", fieldType);
								r.set("isgroup", false);
								table1Data.add(r);
							}
						}
					}
				}
			}
			tableDatas.put("表" + tableCount, table1Data);
			tableCount++;
		}
		return tableDatas;
	}

	private static boolean rowIsNull(XWPFTableRow row, int i) {
		boolean rowisNull = false;

		List<XWPFTableCell> cells = row.getTableCells(); // 每一行的所有列

		for (int j = 0; j < cells.size(); j++) { // 列

			XWPFTableCell cell = cells.get(j);

			// w:vmerge // 控制行合并,<w:vmerge w:val="restart" />,<w:vmerge w:val="continue" />
			// w:gridSpan // 控制列合并

			CTTcPr tcPr = cell.getCTTc().getTcPr();
			// if (cells.size() == 1) {
			// logger.info(String.format("****************** %s , 是否是合并行 :%s, 是否是合并列：%s, 行数据：%s", cell.getText(), tcPr.isSetVMerge() ? "是" : "否", tcPr.isSetGridSpan() ? "是" : "否", cell.getText()));
			// } else {
			logger.info(String.format("第 %s 行 %s 列 = %s , 是否是合并行 :%s, 是否是合并列：%s", i, j, cell.getText(), tcPr.isSetVMerge() ? "是" : "否", tcPr.isSetGridSpan() ? "是" : "否"));
			// }
			if (StrKit.isBlank(cell.getText()) && !tcPr.isSetVMerge()) {
				rowisNull = true;
			}
		}
		if (!rowisNull) {
			logger.info("*****************此行数据均不为空 ");
			logger.info("");
		}
		return rowisNull;
	}

	private static Map<Integer, String> getRowData(XWPFTableRow row) {

		Map<Integer, String> map = new HashMap<>();

		List<XWPFTableCell> cells = row.getTableCells(); // 每一行的所有列

		for (int j = 0; j < cells.size(); j++) { // 列

			XWPFTableCell cell = cells.get(j);

			map.put(j, cell.getText());
		}
		return map;
	}
}
